package uy.org.softtech.cssuite.servicios.impl;

import static org.springframework.util.Assert.notNull;
import static uy.org.softtech.cssuite.helpers.HelperFechaHora.fechaActual;

import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import uy.org.softtech.cssuite.core.Servicio;
import uy.org.softtech.cssuite.entidad.cliente.Cliente;
import uy.org.softtech.cssuite.entidad.finanzas.Cuenta;
import uy.org.softtech.cssuite.entidad.finanzas.Cuenta.Estado;
import uy.org.softtech.cssuite.excepciones.EntidadNoActualizadaException;
import uy.org.softtech.cssuite.excepciones.EntidadNoCreadaException;
import uy.org.softtech.cssuite.excepciones.EntidadNoEliminadaException;
import uy.org.softtech.cssuite.excepciones.EntidadNoEncontradaException;
import uy.org.softtech.cssuite.repositorios.RepositorioClientes;
import uy.org.softtech.cssuite.repositorios.RepositorioCuentas;
import uy.org.softtech.cssuite.servicios.ServiciosClientes;

/**
 * Clase que implementa {@link ServiciosClientes}.
 * 
 * @author fabian.lobo
 * @see ServiciosClientes
 */
@Service(value = "servicios-clientes")
public class ServiciosClientesImpl extends Servicio implements ServiciosClientes {

	private Logger log = Logger.getLogger(getClass());
	
	@Resource(name = "repositorio-clientes" )
	private RepositorioClientes repositorioClientes;
	
	@Resource(name = "repositorio-cuentas" )
	private RepositorioCuentas repositorioCuentas;
	
	/**
	 * Método para verificar que todos los parámetros han sido seteados correctamente.
	 * 
	 * @author fabian.lobo
	 */
	@PostConstruct
	public void inicializacion(){
		notNull(repositorioClientes(), "La propiedad [repositorioClientes] de [" + getClass().getName() + "] no ha sido establecida.");
		notNull(repositorioCuentas(), "La propiedad [repositorioCuentas] de [" + getClass().getName() + "] no ha sido establecida.");
				
		log.info("Implementación de los servicios relacionados a los clientes ha sido inicializado correctamente.");
	}
	
	@Override
	public Set<Cliente> listarClientes() {
		return repositorioClientes().listarClientes();
	}
	
	@Override
	public Cliente buscarCliente(Long id) throws EntidadNoEncontradaException {
		return repositorioClientes().buscar(id);
	}

	@Override
	public Cliente crear(Cliente cliente, String servicio) throws EntidadNoCreadaException {
		return repositorioClientes().crear(cliente, servicio);
	}

	@Override
	public Cliente actualizar(Cliente cliente, String servicio) throws EntidadNoActualizadaException {
		return repositorioClientes().actualizar(cliente, servicio);
	}
	
	@Override
	public void bloquearCliente(Long id) throws EntidadNoEncontradaException, EntidadNoActualizadaException {
		Cliente cliente = buscarCliente(id);
		cliente.setBloqueado(true);
		actualizar(cliente, SERVICIO);
	}

	@Override
	public void desbloquearCliente(Long id) throws EntidadNoEncontradaException, EntidadNoActualizadaException {
		Cliente cliente = buscarCliente(id);
		cliente.setBloqueado(false);
		actualizar(cliente, SERVICIO);
	}

	@Override
	public void eliminarCliente(Long id) throws EntidadNoEncontradaException, EntidadNoEliminadaException {
		Cliente cliente = buscarCliente(id);
		cliente.setEliminado(true);
		try {
			actualizar(cliente, SERVICIO);
		} catch (EntidadNoActualizadaException e) {
			throw new EntidadNoEliminadaException(cliente);
		}
	}
	
	@Override
	public Cuenta buscarCuenta(Long id) throws EntidadNoEncontradaException {
		return repositorioCuentas().buscar(id);
	}
	
	@Override
	public void activarCuenta(Long id) throws EntidadNoEncontradaException, EntidadNoActualizadaException {
		Cuenta cuenta = buscarCuenta(id);
		cuenta.setEstado(Estado.ACTIVA);
		cuenta.setFechaActivacion(fechaActual());
		actualizarCuenta(cuenta, SERVICIO);
	}

	@Override
	public void cancelarCuenta(Long id) throws EntidadNoActualizadaException, EntidadNoEncontradaException {
		Cuenta cuenta = buscarCuenta(id);
		cuenta.setEstado(Estado.CANCELADA);
		actualizarCuenta(cuenta, SERVICIO);
	}

	@Override
	public void cerrarCuenta(Long id) throws EntidadNoActualizadaException, EntidadNoEncontradaException {
		Cuenta cuenta = buscarCuenta(id);
		cuenta.setEstado(Estado.CERRADA);
		cuenta.setFechaCierre(fechaActual());
		actualizarCuenta(cuenta, SERVICIO);
	}

	@Override
	public void desactivarCuenta(Long id) throws EntidadNoActualizadaException, EntidadNoEncontradaException {
		Cuenta cuenta = buscarCuenta(id);
		cuenta.setEstado(Estado.INACTIVA);
		cuenta.setFechaDesactivacion(fechaActual());
		actualizarCuenta(cuenta, SERVICIO);
	}

	@Override
	public Cuenta crearCuenta(Cuenta cuenta, String servicio) throws EntidadNoCreadaException {
		return repositorioCuentas().crear(cuenta, servicio);
	}

	@Override
	public Cuenta actualizarCuenta(Cuenta cuenta, String servicio) throws EntidadNoActualizadaException {
		return repositorioCuentas().actualizar(cuenta, servicio);
	}

	@Override
	public Set<Cuenta> obtenerCuentas(Long cliente) {
		return repositorioCuentas().obtenerCuentas(cliente);
	}
	
	/*
	 *  GETTERS
	 */
	public RepositorioClientes repositorioClientes() {
		return repositorioClientes;
	}
	public RepositorioCuentas repositorioCuentas() {
		return repositorioCuentas;
	}

}
